package com.ch.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ch.web.ResponseDto.xyUser.UserStoreResDto;
import com.ch.web.utils.TokenGenerator;
import com.ch.web.entity.user.XyTokenEntity;
import com.ch.web.entity.user.XyUserEntity;
import com.ch.web.enums.UserEnumCollection;
import com.ch.web.mapper.XyTokenDao;
import com.ch.web.redis.UserMapCache;
import com.ch.web.service.XyTokenService;
import com.ch.web.service.XyUserService;
import com.ch.web.utils.ColaBeanUtils;
import com.ch.web.utils.PageUtils;
import com.ch.web.utils.Query;
import com.ch.web.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.Objects;


@Service("xyTokenService")
public class XyTokenServiceImpl extends ServiceImpl<XyTokenDao, XyTokenEntity> implements XyTokenService {
    @Resource
    UserMapCache userMapCache;
    @Autowired
    XyUserService xyUserService;
    @Value("${token.expire}")
    private Long expire;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<XyTokenEntity> page = this.page(
                new Query<XyTokenEntity>().getPage(params),
                new QueryWrapper<XyTokenEntity>()
        );
        return new PageUtils(page);
    }

    @Override
    public R createToken(XyUserEntity entity) throws Exception {
        XyTokenEntity tokenEntity = this.getById(entity.getUserId());
        //如果token为空 说明没有存储过、
        String token = TokenGenerator.generateValue();
        Date date = new Date();
        Date expireTime = new Date(date.getTime() + expire);
        if (tokenEntity == null) {
            tokenEntity = new XyTokenEntity();
            tokenEntity.setToken(token);
            tokenEntity.setUserId(entity.getUserId());
            updateTokenTime(tokenEntity, date, expireTime);
            //代表登录成功了
            updateUserOnline(entity);
            this.save(tokenEntity);
            userMapCache.setUserToken(token, entity, expireTime);
            UserStoreResDto userStoreResDto = ColaBeanUtils.copyObject(entity, UserStoreResDto::new);
            return Objects.requireNonNull(R.ok().put("token", token)).put("expire", expireTime).put("user", userStoreResDto);
        } else {
            if (entity.getUserOnline() == 1) {
                //代表强制上线者  该号已经上线了 需要重写修改 token
                updateTokenTime(tokenEntity, date, expireTime);
                tokenEntity.setToken(token);
                this.updateById(tokenEntity);
                userMapCache.setUserToken(token, entity, expireTime);
                UserStoreResDto userStoreResDto = ColaBeanUtils.copyObject(entity, UserStoreResDto::new);
                return Objects.requireNonNull(R.error(UserEnumCollection.USER_IS_LOGIN.getCode(), UserEnumCollection.USER_IS_LOGIN.getMessage()).put("token", token)).put("expire", expireTime).put("user", userStoreResDto);
            } else {
                //代表没有用户在线 直接更改状态
                updateTokenTime(tokenEntity, date, expireTime);
                tokenEntity.setToken(token);
                this.updateById(tokenEntity);
                updateUserOnline(entity);
                userMapCache.setUserToken(token, entity, expireTime);
                UserStoreResDto userStoreResDto = ColaBeanUtils.copyObject(entity, UserStoreResDto::new);
                return Objects.requireNonNull(R.ok().put("token", token)).put("expire", expireTime).put("user", userStoreResDto);
            }
        }
    }

    @Override
    public Long getUserIdByToken(String token) {
        Long userId = null;
        try {
            userId=getBaseMapper().selectOne(new QueryWrapper<XyTokenEntity>().eq("token", token)).getUserId();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return userId;

    }

    private void updateUserOnline(XyUserEntity entity) {
        entity.setUserOnline(1);
        this.xyUserService.updateById(entity);
    }

    private void updateTokenTime(XyTokenEntity tokenEntity, Date date, Date expireTime) {
        tokenEntity.setUpdatetime(date);
        tokenEntity.setExpiretime(expireTime);
    }

}
